package engine;

import javax.swing.UIManager;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.*;

import java.awt.Component;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import java.util.Observable;
import java.util.Observer;
import java.util.List;
import java.util.LinkedList;

import model.building.*;
import model.util.*;
import graphics.*;
import java.awt.*;

public class GraphicsEngine extends Engine {
    
    /** Attributs */
    private GameEngine m_gameEngine;
    private JFrame m_frame;
    private GBuildingChooser m_gBuildingChooser;
    private GStatusArea m_gStatusArea;
    private GRessources m_gEconomy;
    private GCity m_gCity;
    private ButtonGroup m_buttonGroup;
	
    /** Constructeurs */
    public GraphicsEngine(GameEngine gameEngine) {
        m_gameEngine = gameEngine;
	
        m_buttonGroup = new ButtonGroup() { 
                public void add(AbstractButton button) {
                    super.add(button);
                    button.addItemListener(new ItemListener() { 
                            public void itemStateChanged(ItemEvent e) {
                                GStatusArea.Viewer button = (GStatusArea.Viewer)e.getItem();
                                if (e.getStateChange() == ItemEvent.SELECTED) button.update(m_gStatusArea);
                            }});
                }};
        
        m_gEconomy = new GRessources(m_gameEngine.getCity().getEconomy());
        m_gCity = new GCity(m_gameEngine.getCity(), m_buttonGroup);
        m_gBuildingChooser = new GBuildingChooser(m_buttonGroup); 
        m_gStatusArea = new GStatusArea(m_gCity);
	
        { /** On ajoute les BuildingFactory au GraphicalBuildingChooser */
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) { 
                    public String getName() { return "Haunted House"; }
                    public Object3D.Shape3D getShape3D() { return HauntedHouse.getShape(); }
                    public boolean canBuy() { return canBuy(HauntedHouse.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return HauntedHouse.getDefaultActivity(); }
                    public Building construct(Vector3D position) {
                        HauntedHouse h = new HauntedHouse(getCity(),position);
                        return construct(h, HauntedHouse.getConstructionCost()); 
                    }
                    public Component createGStatusAreaViewer(Building b) { 
                        HauntedHouse h = (HauntedHouse)b;
                        GActivity ret = new GActivity(h.getActivity(), m_gameEngine.getCity().getEconomy());

                        return ret; 
                    }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "House"; }
                    public Object3D.Shape3D getShape3D() { return House.getShape(); }
                    public boolean canBuy() { return canBuy(House.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return House.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new House(getCity(),position), House.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "Council Flat"; }
                    public Object3D.Shape3D getShape3D() { return CouncilFlat.getShape(); }
                    public boolean canBuy() { return canBuy(CouncilFlat.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return CouncilFlat.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new CouncilFlat(getCity(),position), CouncilFlat.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "Firm"; }
                    public Object3D.Shape3D getShape3D() { return Firm.getShape(); }
                    public boolean canBuy() { return canBuy(Firm.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return Firm.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new Firm(getCity(),position), Firm.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "Farm"; }
                    public Object3D.Shape3D getShape3D() { return Farm.getShape(); }
                    public boolean canBuy() { return canBuy(Farm.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return Farm.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new Farm(getCity(),position), Farm.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "Family Business"; }
                    public Object3D.Shape3D getShape3D() { return FamilyBusiness.getShape(); }
                    public boolean canBuy() { return canBuy(FamilyBusiness.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return FamilyBusiness.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new FamilyBusiness(getCity(),position), FamilyBusiness.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
	    m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "Hair Dresser"; }
                    public Object3D.Shape3D getShape3D() { return HairDresser.getShape(); }
                    public boolean canBuy() { return canBuy(HairDresser.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return HairDresser.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new HairDresser(getCity(),position), HairDresser.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "Hospital"; }
                    public Object3D.Shape3D getShape3D() { return Hospital.getShape(); }
                    public boolean canBuy() { return canBuy(Hospital.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return Hospital.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new Hospital(getCity(),position), Hospital.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
            m_gBuildingChooser.add(new GBuildingFactory(m_gCity) {
                    public String getName() { return "PCPD"; }
                    public Object3D.Shape3D getShape3D() { return PCPD.getShape(); }
                    public boolean canBuy() { return canBuy(PCPD.getConstructionCost()); }
                    public Building.Activity getDefaultActivity() { return PCPD.getDefaultActivity(); }
                    public Building construct(Vector3D position) 
                    { return construct(new PCPD(getCity(),position), PCPD.getConstructionCost()); }
                    public Component createGStatusAreaViewer(Building b) { return null; }
                });
        }
    }

    /** Methodes */
    protected void begin() {
        m_frame = new JFrame(); 
        m_frame.setTitle("ProgressCity 2011 - Vice City");
        m_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
        catch (Exception e) { e.printStackTrace(); } 
	
        JPanel sidePanel = new JPanel(new BorderLayout());
        sidePanel.add(m_gEconomy, BorderLayout.NORTH);
        sidePanel.add(m_gBuildingChooser, BorderLayout.CENTER);
        sidePanel.add(m_gStatusArea, BorderLayout.SOUTH);
	
        m_frame.add(m_gCity, BorderLayout.CENTER);
        m_frame.add(sidePanel, BorderLayout.WEST);
	
        m_frame.pack();
        m_frame.setLocationRelativeTo(null);
        m_frame.setVisible(true);
    }
    
    protected void iteration() { stop(); }

    protected void end() {}

}
